/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE;
using DaveSexton.DocProject.Resources;
using System.Collections.ObjectModel;
using Microsoft.VisualStudio.CommandBars;
using DaveSexton.DocProject.Configuration;

namespace DaveSexton.DocProject
{
	public abstract class ToolBar
	{
		#region Public Properties
		public string UniqueName
		{
			get
			{
				return provider.Name + "_" + name;
			}
		}

		public string Name
		{
			get
			{
				return name;
			}
		}

		public ToolBarCommandCollection Commands
		{
			get
			{
				return commands;
			}
		}

		public virtual bool Enabled
		{
			get
			{
				return true;
			}
		}

		public virtual bool Visible
		{
			get
			{
				return true;
			}
		}

		public virtual int RowIndex
		{
			get
			{
				return (int) MsoBarRow.msoBarRowLast;
			}
		}

		public virtual bool PersistUserChanges
		{
			get
			{
				return true;
			}
		}

		public virtual int Top
		{
			get
			{
				return 0;
			}
		}

		public virtual int Left
		{
			get
			{
				return 0;
			}
		}

		public virtual bool RemoveCommandsOnUnload
		{
			get
			{
				return false;
			}
		}

		[CLSCompliant(false)]
		public virtual MsoBarPosition Position
		{
			get
			{
				return MsoBarPosition.msoBarTop;
			}
		}

		[CLSCompliant(false)]
		public CommandBar CommandBar
		{
			get
			{
				return bar;
			}
			internal set
			{
				bar = value;

				if (bar != null)
					OnCommandBarAttached(EventArgs.Empty);
				else
					OnCommandBarDetached(EventArgs.Empty);
			}
		}

		public BuildEngineProvider Provider
		{
			get
			{
				return provider;
			}
		}
		#endregion

		#region Private / Protected
		private readonly string name;
		private readonly BuildEngineProvider provider;
		private readonly ToolBarCommandCollection commands;
		private CommandBar bar;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="ToolBar" /> class for derived types.
		/// </summary>
		protected ToolBar(BuildEngineProvider provider, string name)
		{
			if (provider == null)
				throw new ArgumentNullException("provider");

			if (string.IsNullOrEmpty(name))
				throw new ArgumentException(Errors.NullOrEmpty, "name");

			this.provider = provider;
			this.name = name;

			commands = new ToolBarCommandCollection(this);
		}
		#endregion

		#region Methods
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "3#"), 
		CLSCompliant(false)]
		protected internal virtual object Execute(string commandName, vsCommandExecOption option, object argument, out bool handled)
		{
			if (commands.Contains(commandName))
			{
				handled = true;
				return commands[commandName].Execute(option, argument);
			}
			else
			{
				handled = false;
				return null;
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate"), 
		System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "3#"), 
		System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "2#"), 
		CLSCompliant(false)]
		protected internal virtual void QueryStatus(string commandName, vsCommandStatusTextWanted textWanted, ref vsCommandStatus status, ref object text)
		{
			if (commands.Contains(commandName))
			{
				ToolBarCommand command = commands[commandName];

				switch (textWanted)
				{
					case vsCommandStatusTextWanted.vsCommandStatusTextWantedNone:
						status = command.Status;
						break;
					case vsCommandStatusTextWanted.vsCommandStatusTextWantedStatus:
						text = command.GetStatusText(status);
						break;
					case vsCommandStatusTextWanted.vsCommandStatusTextWantedName:
						text = command.Name;
						break;
				}
			}
		}
		#endregion

		#region Events
		private readonly object CommandBarAttachedEventLock = new object();
		private EventHandler CommandBarAttachedEvent;
		private readonly object CommandBarDetachedEventLock = new object();
		private EventHandler CommandBarDetachedEvent;

		/// <summary>
		/// Event raised when the <see cref="CommandBar"/> is unloaded from the Visual Studio IDE.
		/// </summary>
		public event EventHandler CommandBarDetached
		{
			add
			{
				lock (CommandBarDetachedEventLock)
				{
					CommandBarDetachedEvent += value;
				}
			}
			remove
			{
				lock (CommandBarDetachedEventLock)
				{
					CommandBarDetachedEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="CommandBarDetached" /> event.
		/// </summary>
		/// <param name="e"><see cref="EventArgs" /> object that provides the arguments for the event.</param>
		protected virtual void OnCommandBarDetached(EventArgs e)
		{
			EventHandler handler = null;

			lock (CommandBarDetachedEventLock)
			{
				handler = CommandBarDetachedEvent;
			}

			if (handler != null)
				handler(this, e);
		}

		/// <summary>
		/// Event raised when the <see cref="CommandBar"/> is created in the Visual Studio IDE.
		/// </summary>
		public event EventHandler CommandBarAttached
		{
			add
			{
				lock (CommandBarAttachedEventLock)
				{
					CommandBarAttachedEvent += value;
				}
			}
			remove
			{
				lock (CommandBarAttachedEventLock)
				{
					CommandBarAttachedEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="CommandBarAttached" /> event.
		/// </summary>
		/// <param name="e"><see cref="EventArgs" /> object that provides the arguments for the event.</param>
		protected virtual void OnCommandBarAttached(EventArgs e)
		{
			EventHandler handler = null;

			lock (CommandBarAttachedEventLock)
			{
				handler = CommandBarAttachedEvent;
			}

			if (handler != null)
				handler(this, e);
		}
		#endregion
	}
}
